package com.beemans.common.ui.views

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import android.view.animation.OvershootInterpolator
import androidx.annotation.ColorRes
import androidx.core.content.ContextCompat
import com.beemans.common.R

/**
 * 描述：圆形进度条
 */
class CircularProgressView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
) : View(context, attrs, defStyleAttr) {

    //初始化背景圆环画笔
    private val mBackPaint: Paint

    //初始化进度圆环画笔
    private val mProgPaint: Paint

    //绘制区域
    private var mRectF: RectF? = null

    //背景圆环渐变色
    private var mBackColorArray = intArrayOf()

    //进度圆环渐变色
    private var mProgColorArray = intArrayOf()

    //圆环进度(0-100)
    private var mProgress = 0

    //背景圆环起始角度
    private var mBackStartAngle = 0f

    //进度圆环起始角度
    private var mProgStartAngle = 270f

    //背景圆环结束角度
    private var mBackEndAngle = 360f

    //进度圆环结束角度
    private var mProgEndAngle = 360f

    init {
        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircularProgressView)

        //初始化背景圆环画笔
        mBackPaint = Paint().apply {
            style = Paint.Style.STROKE // 只描边，不填充
            strokeCap = Paint.Cap.ROUND // 设置圆角
            isAntiAlias = true // 设置抗锯齿
            isDither = true // 设置抖动
            strokeWidth = typedArray.getDimension(
                R.styleable.CircularProgressView_tcp_backWidth,
                5f
            )
            color = typedArray.getColor(
                R.styleable.CircularProgressView_tcp_backColor,
                Color.LTGRAY
            )
        }

        //初始化进度圆环画笔
        mProgPaint = Paint().apply {
            style = Paint.Style.STROKE // 只描边，不填充
            strokeCap = Paint.Cap.ROUND // 设置圆角
            isAntiAlias = true // 设置抗锯齿
            isDither = true // 设置抖动
            strokeWidth = typedArray.getDimension(
                R.styleable.CircularProgressView_tcp_progWidth,
                10f
            )
            color = typedArray.getColor(
                R.styleable.CircularProgressView_tcp_progColor,
                Color.BLUE
            )
        }

        //初始化背景圆环渐变色
        val backStartColor =
            typedArray.getColor(R.styleable.CircularProgressView_tcp_backStartColor, -1)
        val backEndColor =
            typedArray.getColor(R.styleable.CircularProgressView_tcp_backEndColor, -1)
        if (backStartColor != -1 && backEndColor != -1) {
            mBackColorArray = intArrayOf(backStartColor, backEndColor)
        }

        //初始化进度圆环渐变色
        val progStartColor =
            typedArray.getColor(R.styleable.CircularProgressView_tcp_progStartColor, -1)
        val progEndColor =
            typedArray.getColor(R.styleable.CircularProgressView_tcp_progEndColor, -1)
        if (progStartColor != -1 && progEndColor != -1) {
            mProgColorArray = intArrayOf(progStartColor, progEndColor)
        }

        //初始化进度
        mProgress = typedArray.getInteger(R.styleable.CircularProgressView_tcp_progress, mProgress)

        //背景圆环起始角度
        mBackStartAngle = typedArray.getFloat(
            R.styleable.CircularProgressView_tcp_backStartAngle,
            mBackStartAngle
        )

        //进度圆环起始角度
        mProgStartAngle = typedArray.getFloat(
            R.styleable.CircularProgressView_tcp_progStartAngle,
            mProgStartAngle
        )

        //背景圆环结束角度
        mBackEndAngle = typedArray.getFloat(
            R.styleable.CircularProgressView_tcp_backEndAngle,
            mBackEndAngle
        )

        //进度圆环结束角度
        mProgEndAngle = typedArray.getFloat(
            R.styleable.CircularProgressView_tcp_progEndAngle,
            mProgEndAngle
        )

        typedArray.recycle()
    }

    @SuppressLint("DrawAllocation")
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val viewWide = measuredWidth - paddingLeft - paddingRight
        val viewHigh = measuredHeight - paddingTop - paddingBottom
        val minWidth = viewWide.coerceAtMost(viewHigh)
        val maxStrokeWidth = mBackPaint.strokeWidth.coerceAtLeast(mProgPaint.strokeWidth)
        val mRectLength = minWidth - maxStrokeWidth
        val mRectL = paddingLeft + (viewWide - mRectLength) / 2
        val mRectT = paddingTop + (viewHigh - mRectLength) / 2
        mRectF = RectF(mRectL, mRectT, (mRectL + mRectLength), (mRectT + mRectLength))

        //设置进度圆环渐变色
        if (mBackColorArray.size > 1) {
            mBackPaint.shader = LinearGradient(
                0f,
                0f,
                0f,
                measuredWidth.toFloat(),
                mBackColorArray,
                null,
                Shader.TileMode.MIRROR
            )
        }

        //设置进度圆环渐变色
        if (mProgColorArray.size > 1) {
            mProgPaint.shader = LinearGradient(
                0f,
                0f,
                0f,
                measuredWidth.toFloat(),
                mProgColorArray,
                null,
                Shader.TileMode.MIRROR
            )
        }
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        mRectF?.let {
            canvas.drawArc(
                it,
                mBackStartAngle,
                mBackEndAngle,
                false,
                mBackPaint
            )
        }
        mRectF?.let {
            canvas.drawArc(
                it,
                mProgStartAngle,
                mProgEndAngle * mProgress / 100,
                false,
                mProgPaint
            )
        }
    }

    /**
     * 当前进度（0-100）
     */
    var progress: Int
        get() = mProgress
        set(progress) {
            mProgress = progress
            invalidate()
        }

    /**
     * 设置当前进度，并展示进度动画。如果动画时间小于等于0，则不展示动画
     *
     * @param progress 当前进度（0-100）
     * @param animTime 动画时间（毫秒）
     */
    fun setProgress(progress: Int, animTime: Long) {
        if (animTime <= 0) {
            this.progress = progress
        } else {
            val animator = ValueAnimator.ofInt(mProgress, progress)
            animator.addUpdateListener { animation ->
                this.progress = animation.animatedValue as Int
            }
            animator.interpolator = OvershootInterpolator()
            animator.duration = animTime
            animator.start()
        }
    }

    /**
     * 设置背景圆环宽度
     *
     * @param width 背景圆环宽度
     */
    fun setBackWidth(width: Int) {
        mBackPaint.strokeWidth = width.toFloat()
        invalidate()
    }

    /**
     * 设置背景圆环颜色
     *
     * @param color 背景圆环颜色
     */
    fun setBackColor(@ColorRes color: Int) {
        mBackPaint.color = ContextCompat.getColor(context, color)
        invalidate()
    }

    /**
     * 设置背景圆环颜色(支持渐变色)
     *
     * @param startColor 进度圆环开始颜色
     * @param endColor 进度圆环结束颜色
     */
    fun setBackColor(@ColorRes startColor: Int, @ColorRes endColor: Int) {
        mBackColorArray = intArrayOf(
            ContextCompat.getColor(context, startColor),
            ContextCompat.getColor(context, endColor)
        )
        mBackPaint.shader = LinearGradient(
            0f,
            0f,
            0f,
            measuredWidth.toFloat(),
            mBackColorArray,
            null,
            Shader.TileMode.MIRROR
        )
        invalidate()
    }

    /**
     * 设置背景圆环颜色(支持渐变色)
     *
     * @param colorArray 渐变色集合
     */
    fun setBackColor(@ColorRes colorArray: IntArray) {
        if (colorArray.size < 2) return
        mBackColorArray = IntArray(colorArray.size)

        colorArray.forEachIndexed { index, id ->
            mBackColorArray[index] = ContextCompat.getColor(context, id)
        }
        mBackPaint.shader = LinearGradient(
            0f,
            0f,
            0f,
            measuredWidth.toFloat(),
            mBackColorArray,
            null,
            Shader.TileMode.MIRROR
        )
        invalidate()
    }

    /**
     * 设置进度圆环宽度
     *
     * @param width 进度圆环宽度
     */
    fun setProgWidth(width: Int) {
        mProgPaint.strokeWidth = width.toFloat()
        invalidate()
    }

    /**
     * 设置进度圆环颜色
     *
     * @param color 景圆环颜色
     */
    fun setProgColor(@ColorRes color: Int) {
        mProgPaint.color = ContextCompat.getColor(context, color)
        mProgPaint.shader = null
        invalidate()
    }

    /**
     * 设置进度圆环颜色(支持渐变色)
     *
     * @param startColor 进度圆环开始颜色
     * @param firstColor 进度圆环结束颜色
     */
    fun setProgColor(@ColorRes startColor: Int, @ColorRes firstColor: Int) {
        mProgColorArray = intArrayOf(
            ContextCompat.getColor(context, startColor),
            ContextCompat.getColor(context, firstColor)
        )
        mProgPaint.shader = LinearGradient(
            0f,
            0f,
            0f,
            measuredWidth.toFloat(),
            mProgColorArray,
            null,
            Shader.TileMode.MIRROR
        )
        invalidate()
    }

    /**
     * 设置进度圆环颜色(支持渐变色)
     *
     * @param colorArray 渐变色集合
     */
    fun setProgColor(@ColorRes colorArray: IntArray) {
        if (colorArray.size < 2) return
        mProgColorArray = IntArray(colorArray.size)

        colorArray.forEachIndexed { index, id ->
            mProgColorArray[index] = ContextCompat.getColor(context, id)
        }
        mProgPaint.shader = LinearGradient(
            0f,
            0f,
            0f,
            measuredWidth.toFloat(),
            mProgColorArray,
            null,
            Shader.TileMode.MIRROR
        )
        invalidate()
    }
}